<?php

class Cache_File extends Cache {

    public static function checkDriver() {
        return is_writable(self::$options['file']['directory']);
    }

    function __construct() {
        if (!self::checkDriver()) {
            throw new Exception("Can't use this driver for your system!");
        }
    }

    protected function _set($key, $value = "", $tts = 300) {
        $file_path = $this->getFilePath($key);
        $data = $this->encode($value);
        $f = fopen($file_path, "w+");
        fwrite($f, $data);
        fclose($f);
    }

    protected function _get($key) {
        $file_path = $this->getFilePath($key, true);
        if (!file_exists($file_path)) {
            return NULL;
        }
        $content = $this->readfile($file_path);
        $object = $this->decode($content);
        if (self::$options['file']['directory'] && $this->isExpired($object)) {
            @unlink($file_path);
            $this->auto_clean_expired();
            return NULL;
        }
        return $object;
    }

    protected function _delete($key) {
        $file_path = $this->getFilePath($key, true);
        if (@unlink($file_path)) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    protected function _exist($key) {
        return $this->_get($key) ? TRUE : FALSE;
        //$file_path = $this->getFilePath($key, true);
        //return file_exists($file_path) ? TRUE : FALSE;
    }

    protected function _clean() {
        $path = self::$options['file']['directory'];
        $dir = @opendir($path);
        if (!$dir) {
            throw new Yaf_Exception("Can't read PATH:" . $path, 94);
        }
        while ($file = readdir($dir)) {
            if ($file != "." && $file != "..") {
                $filename = $path . "/" . $file;
                if (is_dir($filename)) {
                    $subdir = @opendir($filename);
                    if (!$subdir) {
                        throw new Yaf_Exception("Can't read path:" . $filename, 93);
                    }
                    while ($f = readdir($subdir)) {
                        if ($f != "." && $f != "..") {
                            $file_path = $filename . "/" . $f;
                            unlink($file_path);
                        }
                    }
                } else {
                    unlink($filename);
                }
            }
        }
    }

    protected function _stats() {
        $res = array(
            "info" => "",
            "size" => "",
            "data" => "",
        );
        $path = self::$options['file']['directory'];
        $dir = @opendir($path);
        if (!$dir) {
            throw new Yaf_Exception("Can't read PATH:" . $path, 94);
        }
        $total = 0;
        $removed = 0;
        while ($file = readdir($dir)) {
            if ($file != "." && $file != "..") {
                $filename = $path . "/" . $file;
                if (is_dir($filename)) {
                    // read sub dir
                    $subdir = @opendir($filename);
                    if (!$subdir) {
                        throw new Yaf_Exception("Can't read path:" . $filename, 93);
                    }
                    while ($f = readdir($subdir)) {
                        if ($f != "." && $f != "..") {
                            $file_path = $filename . "/" . $f;
                            $size = filesize($file_path);
                            $object = $this->decode($this->readfile($file_path));
                            if ($this->isExpired($object)) {
                                unlink($file_path);
                                $removed = $removed + $size;
                            }
                            $total = $total + $size;
                        }
                    } // end read subdir
                } else {
                    $size = filesize($filename);
                    $object = $this->decode($this->readfile($filename));
                    if ($this->isExpired($object)) {
                        unlink($filename);
                        $removed = $removed + $size;
                    }
                    $total = $total + $size;
                }
            } // end if
        } // end while
        $res['size'] = $total - $removed;
        $res['info'] = array(
            "Total" => $total,
            "Removed" => $removed,
            "Current" => $res['size'],
        );
        return $res;
    }

    protected function isExpired($object) {
        if (isset($object['expired_in']) && $object['expired_in'] > 0 && isset($object['expired_time']) && time() >= $object['expired_time']) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    protected function auto_clean_expired() {
        $autoclean = $this->get("keyword_clean_up_files");
        if (!$autoclean) {
            $this->set("keyword_clean_up_files", TRUE, 3600 * 24);
            $this->stats();
        }
    }

    private function getFilePath($key, $skip = false) {
        $code = md5($key);
        $path = self::$options['file']['directory'] . (self::$options['file']['subfolder'] ? "/" . substr($code, 0, 2) : '');
        if ($skip == false) {
            if (!file_exists($path)) {
                if (!@mkdir($path, 0777)) {
                    throw new Yaf_Exception("PLEASE CHMOD " . self::$options['file']['directory'] . " - 0777 OR ANY WRITABLE PERMISSION!", 92);
                }
            } elseif (!is_writeable($path)) {
                @chmod($path, 0777);
            }
        }
        $file_path = $path . "/" . $code . "." . self::$options['file']['suffix'];
        return $file_path;
    }

    private function readfile($file) {
        if (function_exists("file_get_contents")) {
            return file_get_contents($file);
        } else {
            $string = "";
            $file_handle = @fopen($file, "r");
            if (!$file_handle) {
                throw new Exception("Can't Read File", 96);
            }
            while (!feof($file_handle)) {
                $line = fgets($file_handle);
                $string .= $line;
            }
            fclose($file_handle);
            return $string;
        }
    }

}
